//  View.hpp
//  PureMVC_C++
//
//  PureMVC Port to C++ by Tang Khai Phuong <phuong.tang@puremvc.org>
//  PureMVC - Copyright(c) 2006-2011 Futurescale, Inc., Some rights reserved.
//  Your reuse is governed by the Creative Commons Attribution 3.0 License
//
//  中文注释：
//  View类是PureMVC框架中的核心组件之一，实现了IView接口。
//  它负责管理视图层，包括Mediator和Observer的注册与通知。
//  View采用Multiton模式实现，确保每个键对应唯一的实例。
//

#if !defined(__PUREMVC_CORE_VIEW_HPP__)
#define __PUREMVC_CORE_VIEW_HPP__

// STL include
#include <string>
#include <exception>
#include <cassert>
#include <stdexcept>
// PureMVC include
#if !defined(__PUREMVC_HPP__)
#define __PUREMVC_INCLUDE__
#include "../PureMVC.hpp"
#endif /* __PUREMVC_HPP__ */
#if defined(PUREMVC_USES_TR1)
#if defined(__GNUC__) || defined(__MINGW32__)
#include <tr1/unordered_map>
#else
#include <unordered_map>
#endif
#else
#include <map>
#endif

#include "../Interfaces/IView.hpp"
#include "../Interfaces/IObserver.hpp"
#include "../Interfaces/INotification.hpp"
#include "../Interfaces/IMediator.hpp"
#include "../Interfaces/IAggregate.hpp"
#include "../Interfaces/IIterator.hpp"
#include "../Patterns/Iterator/Iterator.hpp"

namespace PureMVC
{
    namespace Core
    {
        using Interfaces::IObserver;
        using Interfaces::IView;
        using Interfaces::INotification;
        using Interfaces::IMediator;
        using Interfaces::IAggregate;
        using Interfaces::IIterator;

        /**
         * A Multiton <code>IView</code> implementation.
         *
         * <P>
         * In PureMVC, the <code>View</code> class assumes these responsibilities:
         * <UL>
         * <LI>Maintain a cache of <code>IMediator</code> instances.</LI>
         * <LI>Provide methods for registering, retrieving, and removing <code>IMediators</code>.</LI>
         * <LI>Notifiying <code>IMediators</code> when they are registered or removed.</LI>
         * <LI>Managing the observer lists for each <code>INotification</code> in the application.</LI>
         * <LI>Providing a method for attaching <code>IObservers</code> to an <code>INotification</code>'s observer list.</LI>
         * <LI>Providing a method for broadcasting an <code>INotification</code>.</LI>
         * <LI>Notifying the <code>IObservers</code> of a given <code>INotification</code> when it broadcast.</LI>
         * </UL>
         *
         * @see Patterns/Mediator/Mediator.hpp PureMVC::Patterns::Mediator
         * @see Patterns/Observer/Observer.hpp PureMVC::Patterns::Observer
         * @see Patterns/Observer/Notification.hpp PureMVC::Patterns::Notification
         *
         * 中文注释：
         * View类是IView接口的Multiton实现。
         *
         * 在PureMVC中，View类承担以下责任：
         * 1. 维护IMediator实例的缓存
         * 2. 提供注册、检索和删除IMediator的方法
         * 3. 当IMediator被注册或移除时通知它们
         * 4. 管理应用程序中每个INotification的观察者列表
         * 5. 提供将IObserver附加到INotification的观察者列表的方法
         * 6. 提供广播INotification的方法
         * 7. 当INotification被广播时，通知其所有IObserver
         */
        class PUREMVC_API View : public virtual IView
        {
        protected:
#if defined(PUREMVC_USES_TR1)
            typedef std::tr1::unordered_map<std::string, IMediator*> MediatorMap;
            typedef std::tr1::unordered_multimap<std::string, IObserver*> ObserverMap;
#else
            typedef std::map<std::string, IMediator*> MediatorMap;
            typedef std::multimap<std::string, IObserver*> ObserverMap;
#endif
        protected:
            /**
             * 定义迭代器转换器，仅用于获取中介器名称
             * Define iterator converter for getting mediator name only.
             */
            struct IteratorConverter
#if !defined(__DMC__) // The C++ compiler of Digital Mars cannot resolve this case
            : public std::unary_function<MediatorMap::const_iterator, MediatorMap::key_type>
#endif
            {
            /**
             * 转换操作符
             * Converting operator.
             *
             * @param iterator 内部容器的迭代器
             * @param iterator the iterator of internal container.
             * @return 迭代器中中介器的名称
             * @return the name of mediator inside iterator.
             */
                MediatorMap::key_type const& operator()(MediatorMap::const_iterator const& iterator) const;
            };
            /**
             * 定义内部容器的迭代器范围
             * Define iterator range of internal container.
             */
            struct IteratorRange {
                /**
                 * 获取起始点
                 * Get begin point.
                 *
                 * @return 迭代器的起始位置
                 * @return the begin of iterator.
                 */
                MediatorMap::const_iterator begin(MediatorMap const* const& iterator) const;
                /**
                 * 获取结束点
                 * Get end point.
                 *
                 * @return 迭代器的结束位置
                 * @return the end of iterator.
                 */
                MediatorMap::const_iterator end(MediatorMap const* const& iterator) const;
            };
        public:
            /** 默认的Multiton键 */
            static char const* const DEFAULT_KEY;
        protected:
            // 消息常量
            /** 当尝试创建重复的Multiton实例时抛出的错误消息 */
            static char const* const MULTITON_MSG;
        protected:
            // 此核心的Multiton键
            /** 用于标识View实例的Multiton键 */
            std::string const _multiton_key;
            // 中介器名称到中介器实例的映射
            /** 存储所有注册的Mediator实例的映射表 */
            MediatorMap _mediator_map;
            // 通知名称到观察者列表的映射
            /** 存储所有通知及其对应的观察者列表的映射表 */
            ObserverMap _observer_map;
            // 同步访问
            /** 用于确保线程安全的互斥锁 */
            mutable FastMutex _synchronous_access;
        private:
            /** 禁止拷贝构造函数 */
            View(View const&);
            /** 禁止从IView接口拷贝构造 */
            View(IView const&);
            /** 禁止赋值操作符 */
            View& operator=(View const&);
            /** 禁止从IView接口赋值 */
            View& operator=(IView const&);
        protected:
            /**
             * 根据键查找View实例
             * @param key 要查找的Multiton键
             * @return 找到的View实例，如果不存在则返回nullptr
             */
            static IView* find(std::string const& key);
            /**
             * 插入一个View实例到Multiton映射中
             * @param key 要插入的Multiton键
             * @param view 要插入的View实例
             */
            static void insert(std::string const& key, IView* view);
        public:
            /**
             * 构造函数
             * Constructor.
             *
             * <P>
             * 此<code>IView</code>实现是一个Multiton，
             * 因此不应直接调用构造函数，而应调用静态Multiton工厂方法
             * <code>View::getInstance(key)</code>
             * This <code>IView</code> implementation is a Multiton,
             * so you should not call the constructor
             * directly, but instead call the static Multiton
             * Factory method <code>View::getInstance(key)</code>
             *
             * @throws Error 如果已为此Multiton键构造了实例，则抛出错误
             * @throws Error Error if instance for this Multiton key has already been constructed
             *
             * @param key 可选的Multiton键，默认为DEFAULT_KEY
             */
            explicit View(std::string const& key = PureMVC::Core::View::DEFAULT_KEY);
        protected:
            /**
             * 构造函数（模板版本）
             * Constructor.
             *
             * <P>
             * 支持在基类（<code>View</code>）的构造函数中调用虚方法。
             * Support call virtual method in constructor of base class (<code>View</code>).
             *
             * 条件：派生类（继承自<code>View</code>的类）必须实现initializeView方法
             * Condition: Derived class (class inherit from <code>View</code>) must implement method: initializeView
             *
             * 请按以下方式使用：
             * Please use in this way:
             * <code>
             * 
             * ConcreateView::ConcreateView(void)
             * :View(this)
             * {
             *     // 你的代码在这里
             *     // Your code here
             * }
             * </code>
             *
             * 工厂方法 <code>View::getInstance( key )</code>
             * Factory method <code>View::getInstance( key )</code>
             *
             * @throws Error 如果已为此Multiton键构造了实例，则抛出错误
             * @throws Error Error if instance for this Multiton key has already been constructed
             *
             * @param instance 派生类实例的指针
             * @param key 可选的Multiton键，默认为DEFAULT_KEY
             */
            template<typename _DerivedType>
            explicit View(_DerivedType* instance, std::string const& key = PureMVC::Core::View::DEFAULT_KEY)
                : _multiton_key(key)
            {
                if (find(key))
                    throw std::runtime_error(MULTITON_MSG);
                insert(_multiton_key, this);
                instance->_DerivedType::initializeView();
            }

            /**
             * 初始化单例View实例
             * Initialize the Singleton View instance.
             *
             * <P>
             * 由构造函数自动调用，这是在子类中初始化单例实例
             * 而不重写构造函数的机会。
             * Called automatically by the constructor, this
             * is your opportunity to initialize the Singleton
             * instance in your subclass without overriding the
             * constructor.</P>
             *
             * @return void
             */
            virtual void initializeView(void);

        public:
            /**
             * View单例工厂方法
             * View Singleton Factory method.
             *
             * @param key 可选的Multiton键，默认为DEFAULT_KEY
             * @return <code>View</code>的单例实例
             * @return the Singleton instance of <code>View</code>
             */
            static IView& getInstance(std::string const& key = PureMVC::Core::View::DEFAULT_KEY);

            /**
             * 注册一个<code>IObserver</code>以接收具有给定名称的<code>INotifications</code>通知
             * Register an <code>IObserver</code> to be notified
             * of <code>INotifications</code> with a given name.
             *
             * @param notification_name 要通知此<code>IObserver</code>的<code>INotifications</code>名称
             * @param notification_name the name of the <code>INotifications</code> to notify this <code>IObserver</code> of
             * @param observer 要注册的<code>IObserver</code>
             * @param observer the <code>IObserver</code> to register
             */
            virtual void registerObserver (std::string const& notification_name, IObserver* observer);

            /**
             * 通知特定<code>INotification</code>的所有<code>IObservers</code>
             * Notify the <code>IObservers</code> for a particular <code>INotification</code>.
             *
             * <P>
             * 此<code>INotification</code>列表中所有先前附加的<code>IObservers</code>
             * 将按注册顺序被通知，并传递对<code>INotification</code>的引用。
             * All previously attached <code>IObservers</code> for this <code>INotification</code>'s
             * list are notified and are passed a reference to the <code>INotification</code> in
             * the order in which they were registered.</P>
             *
             * @param notification 要通知<code>IObservers</code>的<code>INotification</code>
             * @param notification the <code>INotification</code> to notify <code>IObservers</code> of.
             */
            virtual void notifyObservers(INotification const& notification);

            /**
             * 从给定通知名称的观察者列表中移除具有特定notifyContext的观察者
             * Remove the observer for a given notifyContext from an observer list for a given Notification name.
             * <P>
             * @param notification_name 要从中移除观察者的列表名称
             * @param notification_name which observer list to remove from
             * @param notify_context 要移除的观察者的notify_context对象
             * @param notify_context remove the observer with this object as its notify_context
             */
            virtual void removeObserver(std::string const& notification_name, void const* notify_context);

            /**
             * 向<code>View</code>注册一个<code>IMediator</code>实例
             * Register an <code>IMediator</code> instance with the <code>View</code>.
             *
             * <P>
             * 注册<code>IMediator</code>以便可以通过名称检索它，
             * 并进一步查询<code>IMediator</code>的<code>INotification</code>兴趣。
             * Registers the <code>IMediator</code> so that it can be retrieved by name,
             * and further interrogates the <code>IMediator</code> for its
             * <code>INotification</code> interests.</P>
             * <P>
             * 如果<code>IMediator</code>返回任何要通知的<code>INotification</code>名称，
             * 将创建一个<code>Observer</code>，封装<code>IMediator</code>实例的<code>handleNotification</code>方法，
             * 并将其注册为<code>IMediator</code>感兴趣的所有<code>INotifications</code>的<code>Observer</code>。
             * If the <code>IMediator</code> returns any <code>INotification</code>
             * names to be notified about, an <code>Observer</code> is created encapsulating
             * the <code>IMediator</code> instance's <code>handleNotification</code> method
             * and registering it as an <code>Observer</code> for all <code>INotifications</code> the
             * <code>IMediator</code> is interested in.</p>
             *
             * @param mediator 对<code>IMediator</code>实例的引用
             * @param mediator a reference to the <code>IMediator</code> instance
             */
            virtual void registerMediator(IMediator* mediator);

            /**
             * 从<code>View</code>中检索一个<code>IMediator</code>（常量版本）
             * Retrieve an <code>IMediator</code> from the <code>View</code>.
             *
             * @param mediator_name 要检索的<code>IMediator</code>实例的名称
             * @param mediator_name the name of the <code>IMediator</code> instance to retrieve.
             * @return 先前用给定<code>mediator_name</code>注册的<code>IMediator</code>实例
             * @return the <code>IMediator</code> instance previously registered with the given <code>mediator_name</code>.
             */
            virtual IMediator const& retrieveMediator(std::string const& mediator_name) const;

            /**
             * 从<code>View</code>中检索一个<code>IMediator</code>（非常量版本）
             * Retrieve an <code>IMediator</code> from the <code>View</code>.
             *
             * @param mediator_name 要检索的<code>IMediator</code>实例的名称
             * @param mediator_name the name of the <code>IMediator</code> instance to retrieve.
             * @return 先前用给定<code>mediator_name</code>注册的<code>IMediator</code>实例
             * @return the <code>IMediator</code> instance previously registered with the given <code>mediator_name</code>.
             */
            virtual IMediator& retrieveMediator(std::string const& mediator_name);

            /**
             * 从<code>View</code>中移除一个<code>IMediator</code>
             * Remove an <code>IMediator</code> from the <code>View</code>.
             *
             * @param mediator_name 要移除的<code>IMediator</code>实例的名称
             * @param mediator_name name of the <code>IMediator</code> instance to be removed.
             * @return 从<code>View</code>中移除的<code>IMediator</code>
             * @return the <code>IMediator</code> that was removed from the <code>View</code>
             */
            virtual IMediator* removeMediator(std::string const& mediator_name);

            /**
             * 检查是否注册了指定的Mediator
             * Check if a Mediator is registered or not
             *
             * @param mediator_name 要检查的Mediator名称
             * @param mediator_name
             * @return 当前是否用给定的<code>mediator_name</code>注册了Mediator
             * @return whether a Mediator is registered with the given <code>mediator_name</code>.
             */
            virtual bool hasMediator(std::string const& mediator_name) const;

            /**
             * 列出所有中介器的名称
             * List all names of mediator
             *
             * @return <code>mediator_name</code>的聚合容器
             * @return the aggregate container of <code>mediator_name</code>.
             */
            virtual MediatorNames listMediatorNames(void) const;

            /**
             * 移除一个IView实例
             * Remove an IView instance
             *
             * @param key 要移除的IView实例的键
             * @param key of IView instance to remove
             */
            static void removeView(std::string const& key);

            /**
             * 虚析构函数
             * Virtual destructor.
             */
            virtual ~View(void);
        };
    }
}

#endif /* __PUREMVC_CORE_VIEW_HPP__ */
